<template><div><h2 id="视图" tabindex="-1"><a class="header-anchor" href="#视图"><span>视图</span></a></h2>
<p>视图是 <a href="https://zh.wikipedia.org/wiki/MVC" target="_blank" rel="noopener noreferrer">MVC</a> 模式中的一部分，它是展示数据到终端用户的代码。在 Web 应用中，根据 <em>视图模板</em> 来创建视图，视图模板为PHP脚本文件，主要包含 HTML 代码和展示类 PHP 代码，通过 <code v-pre>yii\web\View</code> 视图应用组件来管理，该组件主要提供通用方法帮助视图构造和渲染，为了简单起见，我们将视图模板或视图模板文件统称为视图。</p>
<h2 id="创建视图" tabindex="-1"><a class="header-anchor" href="#创建视图"><span>创建视图</span></a></h2>
<p>如上所述，视图为包含 HTML 和 PHP 代码的 PHP 脚本，如下代码为一个登录表单的视图，可看到 PHP 代码用来生成动态内容，如页面标题和表单，HTML 代码把它组织成一个漂亮的 HTML 页面。</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token php language-php"><span class="token delimiter important">&lt;?php</span></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">yii<span class="token punctuation">\</span>helpers<span class="token punctuation">\</span>Html</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">yii<span class="token punctuation">\</span>widgets<span class="token punctuation">\</span>ActiveForm</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token comment">/* @var $this yii\web\View */</span></span>
<span class="line"><span class="token comment">/* @var $form yii\widgets\ActiveForm */</span></span>
<span class="line"><span class="token comment">/* @var $model app\models\LoginForm */</span></span>
<span class="line"></span>
<span class="line"><span class="token variable">$this</span><span class="token operator">-></span><span class="token property">title</span> <span class="token operator">=</span> <span class="token string single-quoted-string">'Login'</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token delimiter important">?></span></span></span>
<span class="line"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>h1</span><span class="token punctuation">></span></span><span class="token php language-php"><span class="token delimiter important">&lt;?=</span> <span class="token class-name static-context">Html</span><span class="token operator">::</span><span class="token function">encode</span><span class="token punctuation">(</span><span class="token variable">$this</span><span class="token operator">-></span><span class="token property">title</span><span class="token punctuation">)</span> <span class="token delimiter important">?></span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>h1</span><span class="token punctuation">></span></span></span>
<span class="line"></span>
<span class="line"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>p</span><span class="token punctuation">></span></span>Please fill out the following fields to login:<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>p</span><span class="token punctuation">></span></span></span>
<span class="line"></span>
<span class="line"><span class="token php language-php"><span class="token delimiter important">&lt;?php</span> <span class="token variable">$form</span> <span class="token operator">=</span> <span class="token class-name static-context">ActiveForm</span><span class="token operator">::</span><span class="token function">begin</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token delimiter important">?></span></span></span>
<span class="line">    <span class="token php language-php"><span class="token delimiter important">&lt;?=</span> <span class="token variable">$form</span><span class="token operator">-></span><span class="token function">field</span><span class="token punctuation">(</span><span class="token variable">$model</span><span class="token punctuation">,</span> <span class="token string single-quoted-string">'username'</span><span class="token punctuation">)</span> <span class="token delimiter important">?></span></span></span>
<span class="line">    <span class="token php language-php"><span class="token delimiter important">&lt;?=</span> <span class="token variable">$form</span><span class="token operator">-></span><span class="token function">field</span><span class="token punctuation">(</span><span class="token variable">$model</span><span class="token punctuation">,</span> <span class="token string single-quoted-string">'password'</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">passwordInput</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token delimiter important">?></span></span></span>
<span class="line">    <span class="token php language-php"><span class="token delimiter important">&lt;?=</span> <span class="token class-name static-context">Html</span><span class="token operator">::</span><span class="token function">submitButton</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'Login'</span><span class="token punctuation">)</span> <span class="token delimiter important">?></span></span></span>
<span class="line"><span class="token php language-php"><span class="token delimiter important">&lt;?php</span> <span class="token class-name static-context">ActiveForm</span><span class="token operator">::</span><span class="token function">end</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token delimiter important">?></span></span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>在视图中，可访问 <code v-pre>$this</code> 指向 <code v-pre>yii\web\View</code> 视图组件来管理和渲染这个视图文件。</p>
<p>除了 <code v-pre>$this</code> 之外，上述示例中的视图有其他预定义变量如 <code v-pre>$model</code>，这些变量代表从 <a href="https://github.com/yiisoft/yii2/blob/master/docs/guide-zh-CN/structure-controllers.md" target="_blank" rel="noopener noreferrer">控制器</a> 或其他触发 <a href="https://github.com/yiisoft/yii2/blob/master/docs/guide-zh-CN/structure-views.md#rendering-views" target="_blank" rel="noopener noreferrer">视图渲染</a> 的对象 <em>传入</em> 到视图的数据。</p>
<blockquote>
<p>Tip: 将预定义变量列到视图文件头部注释处，这样可被 IDE 编辑器（如 phpstorm）识别，也是生成视图文档的好方法。</p>
</blockquote>
<h3 id="安全" tabindex="-1"><a class="header-anchor" href="#安全"><span>安全</span></a></h3>
<p>当创建生成HTML页面的视图时，在显示之前将用户输入数据进行转码和过滤非常重要，否则，你的应用可能会被 <a href="https://zh.wikipedia.org/wiki/%E8%B7%A8%E7%B6%B2%E7%AB%99%E6%8C%87%E4%BB%A4%E7%A2%BC" target="_blank" rel="noopener noreferrer">XSS（跨站脚本）</a> 攻击。</p>
<p>要显示纯文本，先调用 [[yii\helpers\Html::encode()]] 进行转码，例如，如下代码将用户名在显示前先转码：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token php language-php"><span class="token delimiter important">&lt;?php</span></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">yii<span class="token punctuation">\</span>helpers<span class="token punctuation">\</span>Html</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token delimiter important">?></span></span></span>
<span class="line"></span>
<span class="line"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>username<span class="token punctuation">"</span></span><span class="token punctuation">></span></span></span>
<span class="line">    <span class="token php language-php"><span class="token delimiter important">&lt;?=</span> <span class="token class-name static-context">Html</span><span class="token operator">::</span><span class="token function">encode</span><span class="token punctuation">(</span><span class="token variable">$user</span><span class="token operator">-></span><span class="token property">name</span><span class="token punctuation">)</span> <span class="token delimiter important">?></span></span></span>
<span class="line"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">></span></span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>要显示HTML内容，先调用 [[yii\helpers\HtmlPurifier]] 过滤内容，例如如下代码将提交内容在显示前先过滤：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token php language-php"><span class="token delimiter important">&lt;?php</span></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">yii<span class="token punctuation">\</span>helpers<span class="token punctuation">\</span>HtmlPurifier</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token delimiter important">?></span></span></span>
<span class="line"></span>
<span class="line"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>post<span class="token punctuation">"</span></span><span class="token punctuation">></span></span></span>
<span class="line">    <span class="token php language-php"><span class="token delimiter important">&lt;?=</span> <span class="token class-name static-context">HtmlPurifier</span><span class="token operator">::</span><span class="token function">process</span><span class="token punctuation">(</span><span class="token variable">$post</span><span class="token operator">-></span><span class="token property">text</span><span class="token punctuation">)</span> <span class="token delimiter important">?></span></span></span>
<span class="line"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">></span></span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><blockquote>
<p>Tip: HTMLPurifier 在保证输出数据安全上做的不错，但性能不佳，如果你的应用需要高性能可考虑 <a href="https://github.com/yiisoft/yii2/blob/master/docs/guide-zh-CN/caching-overview.md" target="_blank" rel="noopener noreferrer">缓存</a> 过滤后的结果。</p>
</blockquote>
<h3 id="组织视图" tabindex="-1"><a class="header-anchor" href="#组织视图"><span>组织视图</span></a></h3>
<p>与 <a href="https://github.com/yiisoft/yii2/blob/master/docs/guide-zh-CN/structure-controllers.md" target="_blank" rel="noopener noreferrer">控制器</a> 和 <a href="https://github.com/yiisoft/yii2/blob/master/docs/guide-zh-CN/structure-models.md" target="_blank" rel="noopener noreferrer">模型</a> 类似，在组织视图上有一些约定：</p>
<ul>
<li>控制器渲染的视图文件默认放在 <code v-pre>@app/views/ControllerID</code> 目录下，其中 <code v-pre>ControllerID</code> 对应 <a href="https://github.com/yiisoft/yii2/blob/master/docs/guide-zh-CN/structure-controllers.md#routes" target="_blank" rel="noopener noreferrer">控制器 ID</a>, 例如控制器类为 <code v-pre>PostController</code>，视图文件目录应为 <code v-pre>@app/views/post</code>，控制器类 <code v-pre>PostCommentController</code> 对应的目录为 <code v-pre>@app/views/post-comment</code>，如果是模块中的控制器，目录应为 [[yii\base\Module::basePath]] 模块目录下的 <code v-pre>views/ControllerID</code> 目录；</li>
<li>对于 <a href="https://github.com/yiisoft/yii2/blob/master/docs/guide-zh-CN/structure-widgets.md" target="_blank" rel="noopener noreferrer">小部件</a> 渲染的视图文件默认放在 <code v-pre>WidgetPath/views</code> 目录，其中 <code v-pre>WidgetPath</code> 代表小部件类文件所在的目录；</li>
<li>对于其他对象渲染的视图文件，建议遵循和小部件相似的规则。</li>
</ul>
<p>可覆盖控制器或小部件的 [[yii\base\ViewContextInterface::getViewPath()]] 方法来自定义视图文件默认目录。</p>
<h2 id="渲染视图" tabindex="-1"><a class="header-anchor" href="#渲染视图"><span>渲染视图</span></a></h2>
<p>可在 <a href="https://github.com/yiisoft/yii2/blob/master/docs/guide-zh-CN/structure-controllers.md" target="_blank" rel="noopener noreferrer">控制器</a>, <a href="https://github.com/yiisoft/yii2/blob/master/docs/guide-zh-CN/structure-widgets.md" target="_blank" rel="noopener noreferrer">小部件</a>，或其他地方调用渲染视图方法来渲染视图，该方法类似以下格式：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token doc-comment comment">/**</span>
<span class="line"> * <span class="token keyword">@param</span> <span class="token class-name"><span class="token keyword">string</span></span> <span class="token parameter">$view</span> 视图名或文件路径，由实际的渲染方法决定</span>
<span class="line"> * <span class="token keyword">@param</span> <span class="token class-name"><span class="token keyword">array</span></span> <span class="token parameter">$params</span> 传递给视图的数据</span>
<span class="line"> * <span class="token keyword">@return</span> <span class="token class-name"><span class="token keyword">string</span></span> 渲染结果</span>
<span class="line"> */</span></span>
<span class="line"><span class="token function">methodName</span><span class="token punctuation">(</span><span class="token variable">$view</span><span class="token punctuation">,</span> <span class="token variable">$params</span> <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">)</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h3 id="控制器中渲染" tabindex="-1"><a class="header-anchor" href="#控制器中渲染"><span>控制器中渲染</span></a></h3>
<p>在 <a href="https://github.com/yiisoft/yii2/blob/master/docs/guide-zh-CN/structure-controllers.md" target="_blank" rel="noopener noreferrer">控制器</a> 中，可调用以下控制器方法来渲染视图：</p>
<ul>
<li>[[yii\base\Controller::render()]]: 渲染一个 <a href="https://github.com/yiisoft/yii2/blob/master/docs/guide-zh-CN/structure-views.md#named-views" target="_blank" rel="noopener noreferrer">视图名</a> 并使用一个 <a href="https://github.com/yiisoft/yii2/blob/master/docs/guide-zh-CN/structure-views.md#layouts" target="_blank" rel="noopener noreferrer">布局</a> 返回到渲染结果。</li>
<li>[[yii\base\Controller::renderPartial()]]: 渲染一个 <a href="https://github.com/yiisoft/yii2/blob/master/docs/guide-zh-CN/structure-views.md#named-views" target="_blank" rel="noopener noreferrer">视图名</a> 并且不使用布局。</li>
<li>[[yii\web\Controller::renderAjax()]]: 渲染一个 <a href="https://github.com/yiisoft/yii2/blob/master/docs/guide-zh-CN/structure-views.md#named-views" target="_blank" rel="noopener noreferrer">视图名</a> 并且不使用布局， 并注入所有注册的JS/CSS脚本和文件，通常使用在响应AJAX网页请求的情况下。</li>
<li>[[yii\base\Controller::renderFile()]]: 渲染一个视图文件目录或 <a href="https://github.com/yiisoft/yii2/blob/master/docs/guide-zh-CN/concept-aliases.md" target="_blank" rel="noopener noreferrer">别名</a>下的视图文件。</li>
<li>[[yii\base\Controller::renderContent()]]: renders a static string by embedding it into the currently applicable <a href="https://github.com/yiisoft/yii2/blob/master/docs/guide-zh-CN/structure-views.md#layouts" target="_blank" rel="noopener noreferrer">layout</a>. This method is available since version 2.0.1.</li>
</ul>
<p>例如：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">namespace</span> <span class="token package">app<span class="token punctuation">\</span>controllers</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">Yii</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">app<span class="token punctuation">\</span>models<span class="token punctuation">\</span>Post</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">yii<span class="token punctuation">\</span>web<span class="token punctuation">\</span>Controller</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">yii<span class="token punctuation">\</span>web<span class="token punctuation">\</span>NotFoundHttpException</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">class</span> <span class="token class-name-definition class-name">PostController</span> <span class="token keyword">extends</span> <span class="token class-name">Controller</span></span>
<span class="line"><span class="token punctuation">{</span></span>
<span class="line">    <span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">actionView</span><span class="token punctuation">(</span><span class="token variable">$id</span><span class="token punctuation">)</span></span>
<span class="line">    <span class="token punctuation">{</span></span>
<span class="line">        <span class="token variable">$model</span> <span class="token operator">=</span> <span class="token class-name static-context">Post</span><span class="token operator">::</span><span class="token function">findOne</span><span class="token punctuation">(</span><span class="token variable">$id</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line">        <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token variable">$model</span> <span class="token operator">===</span> <span class="token constant">null</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">            <span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name">NotFoundHttpException</span><span class="token punctuation">;</span></span>
<span class="line">        <span class="token punctuation">}</span></span>
<span class="line"></span>
<span class="line">        <span class="token comment">// 渲染一个名称为"view"的视图并使用布局</span></span>
<span class="line">        <span class="token keyword">return</span> <span class="token variable">$this</span><span class="token operator">-></span><span class="token function">render</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'view'</span><span class="token punctuation">,</span> <span class="token punctuation">[</span></span>
<span class="line">            <span class="token string single-quoted-string">'model'</span> <span class="token operator">=></span> <span class="token variable">$model</span><span class="token punctuation">,</span></span>
<span class="line">        <span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line">    <span class="token punctuation">}</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h3 id="小部件中渲染" tabindex="-1"><a class="header-anchor" href="#小部件中渲染"><span>小部件中渲染</span></a></h3>
<p>在 <a href="https://github.com/yiisoft/yii2/blob/master/docs/guide-zh-CN/structure-widgets.md" target="_blank" rel="noopener noreferrer">小部件</a> 中，可调用以下小部件方法来渲染视图：</p>
<ul>
<li>[[yii\base\Widget::render()]]: 渲染一个 <a href="https://github.com/yiisoft/yii2/blob/master/docs/guide-zh-CN/structure-views.md#named-views" target="_blank" rel="noopener noreferrer">视图名</a>.</li>
<li>[[yii\base\Widget::renderFile()]]: 渲染一个视图文件目录或 <a href="https://github.com/yiisoft/yii2/blob/master/docs/guide-zh-CN/concept-aliases.md" target="_blank" rel="noopener noreferrer">别名</a>下的视图文件。</li>
</ul>
<p>例如：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">namespace</span> <span class="token package">app<span class="token punctuation">\</span>components</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">yii<span class="token punctuation">\</span>base<span class="token punctuation">\</span>Widget</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">yii<span class="token punctuation">\</span>helpers<span class="token punctuation">\</span>Html</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">class</span> <span class="token class-name-definition class-name">ListWidget</span> <span class="token keyword">extends</span> <span class="token class-name">Widget</span></span>
<span class="line"><span class="token punctuation">{</span></span>
<span class="line">    <span class="token keyword">public</span> <span class="token variable">$items</span> <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line">    <span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">run</span><span class="token punctuation">(</span><span class="token punctuation">)</span></span>
<span class="line">    <span class="token punctuation">{</span></span>
<span class="line">        <span class="token comment">// 渲染一个名为 "list" 的视图</span></span>
<span class="line">        <span class="token keyword">return</span> <span class="token variable">$this</span><span class="token operator">-></span><span class="token function">render</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'list'</span><span class="token punctuation">,</span> <span class="token punctuation">[</span></span>
<span class="line">            <span class="token string single-quoted-string">'items'</span> <span class="token operator">=></span> <span class="token variable">$this</span><span class="token operator">-></span><span class="token property">items</span><span class="token punctuation">,</span></span>
<span class="line">        <span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line">    <span class="token punctuation">}</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h3 id="视图中渲染" tabindex="-1"><a class="header-anchor" href="#视图中渲染"><span>视图中渲染</span></a></h3>
<p>可以在视图中渲染另一个视图，可以调用[[yii\base\View|view component]]视图组件提供的以下方法：</p>
<ul>
<li>
<p>[[yii\base\View::render()]]: 渲染一个 <a href="https://github.com/yiisoft/yii2/blob/master/docs/guide-zh-CN/structure-views.md#named-views" target="_blank" rel="noopener noreferrer">视图名</a>.</p>
</li>
<li>
<p>[[yii\web\View::renderAjax()]]: 渲染一个 <a href="https://github.com/yiisoft/yii2/blob/master/docs/guide-zh-CN/structure-views.md#named-views" target="_blank" rel="noopener noreferrer">视图名</a> 并注入所有注册的JS/CSS脚本和文件，通常使用在响应AJAX网页请求的情况下。</p>
</li>
<li>
<p>[[yii\base\View::renderFile()]]: 渲染一个视图文件目录或 <a href="https://github.com/yiisoft/yii2/blob/master/docs/guide-zh-CN/concept-aliases.md" target="_blank" rel="noopener noreferrer">别名</a>下的视图文件。</p>
</li>
</ul>
<p>例如，视图中的如下代码会渲染该视图所在目录下的 <code v-pre>_overview.php</code> 视图文件， 记住视图中 <code v-pre>$this</code> 对应 [[yii\base\View|view]] 组件:</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token php language-php"><span class="token delimiter important">&lt;?=</span> <span class="token variable">$this</span><span class="token operator">-></span><span class="token function">render</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'_overview'</span><span class="token punctuation">)</span> <span class="token delimiter important">?></span></span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><h3 id="其他地方渲染" tabindex="-1"><a class="header-anchor" href="#其他地方渲染"><span>其他地方渲染</span></a></h3>
<p>在任何地方都可以通过表达式 <code v-pre>Yii::$app-&gt;view</code> 访问 <code v-pre>yii\base\View</code> 视图应用组件，调用它的如前所述的方法渲染视图，例如：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token comment">// 显示视图文件 "@app/views/site/license.php"</span></span>
<span class="line"><span class="token keyword">echo</span> <span class="token class-name class-name-fully-qualified static-context"><span class="token punctuation">\</span>Yii</span><span class="token operator">::</span><span class="token variable">$app</span><span class="token operator">-></span><span class="token property">view</span><span class="token operator">-></span><span class="token function">renderFile</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'@app/views/site/license.php'</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div></div></div><h3 id="视图名" tabindex="-1"><a class="header-anchor" href="#视图名"><span>视图名</span></a></h3>
<p>渲染视图时，可指定一个视图名或视图文件路径，又或者别名，大多数情况下使用前者因为前者简洁灵活，我们称用名字的视图为 <em>视图名</em>.</p>
<p>视图名可以依据以下规则到对应的视图文件路径：</p>
<ul>
<li>视图名可省略文件扩展名，这种情况下使用 <code v-pre>.php</code> 作为扩展， 视图名 <code v-pre>about</code> 对应到 <code v-pre>about.php</code> 文件名；</li>
<li>视图名以双斜杠 <code v-pre>//</code> 开头，对应的视图文件路径为 <code v-pre>@app/views/ViewName</code>，也就是说视图文件在 [[yii\base\Application::viewPath|application’s view path]] 路径下找，例如 <code v-pre>//site/about</code> 对应到 <code v-pre>@app/views/site/about.php</code>。</li>
<li>视图名以单斜杠<code v-pre>/</code>开始，视图文件路径以当前使用 <a href="https://github.com/yiisoft/yii2/blob/master/docs/guide-zh-CN/structure-modules.md" target="_blank" rel="noopener noreferrer">模块</a> 的 [[yii\base\Module::viewPath]] 视图路径开始，如果不存在模块，使用 <code v-pre>@app/views/ViewName</code> 开始，例如，如果当前模块为<code v-pre>user</code>，<code v-pre>/user/create</code> 对应成 <code v-pre>@app/modules/user/views/user/create.php</code>，如果不在模块中，<code v-pre>/user/create</code>对应 <code v-pre>@app/views/user/create.php</code>。</li>
<li>如果 [[yii\base\View::context]] 渲染视图并且上下文实现了 <code v-pre>yii\base\ViewContextInterface</code>, 视图文件路径由上下文的 [[yii\base\ViewContextInterface::getViewPath()]] 视图路径开始，这种主要用在控制器和小部件中渲染视图，例如，如果上下文为控制器 <code v-pre>SiteController</code>，<code v-pre>site/about</code> 对应到 <code v-pre>@app/views/site/about.php</code>。</li>
<li>如果视图渲染另一个视图，包含另一个视图文件的目录以当前视图的文件路径开始， 例如被视图<code v-pre>@app/views/post/index.php</code> 渲染的 <code v-pre>item</code> 对应到 <code v-pre>@app/views/post/item</code>。</li>
</ul>
<p>根据以上规则，在控制器中 <code v-pre>app\controllers\PostController</code> 调用 <code v-pre>$this-&gt;render('view')</code>，实际上渲染 <code v-pre>@app/views/post/view.php</code> 视图文件，当在该视图文件中调用 <code v-pre>$this-&gt;render('_overview')</code> 会渲染 <code v-pre>@app/views/post/_overview.php</code> 视图文件。</p>
<h3 id="视图中访问数据" tabindex="-1"><a class="header-anchor" href="#视图中访问数据"><span>视图中访问数据</span></a></h3>
<p>在视图中有两种方式访问数据：推送和拉取。</p>
<p>推送方式，是通过视图渲染方法的第二个参数传递数据，数据格式应为名称-值的数组，视图渲染时，调用 PHP <code v-pre>extract()</code> 方法将该数组转换为视图可访问的变量。例如，如下控制器的渲染视图代码推送 2 个变量到 <code v-pre>report</code> 视图：<code v-pre>$foo = 1</code> 和 <code v-pre>$bar = 2</code>。</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">echo</span> <span class="token variable">$this</span><span class="token operator">-></span><span class="token function">render</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'report'</span><span class="token punctuation">,</span> <span class="token punctuation">[</span></span>
<span class="line">    <span class="token string single-quoted-string">'foo'</span> <span class="token operator">=></span> <span class="token number">1</span><span class="token punctuation">,</span></span>
<span class="line">    <span class="token string single-quoted-string">'bar'</span> <span class="token operator">=></span> <span class="token number">2</span><span class="token punctuation">,</span></span>
<span class="line"><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>拉取方式，可让视图从 <code v-pre>yii\base\View</code> 视图组件或其他对象中主动获得数据（如 <code v-pre>Yii::$app</code>），在视图中使用如下表达式 <code v-pre>$this-&gt;context</code> 可获取到控制器ID，可让你在 <code v-pre>report</code> 视图中获取控制器的任意属性或方法，如以下代码获取控制器ID。</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line">The controller ID is: <span class="token php language-php"><span class="token delimiter important">&lt;?=</span> <span class="token variable">$this</span><span class="token operator">-></span><span class="token property">context</span><span class="token operator">-></span><span class="token property">id</span> <span class="token delimiter important">?></span></span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p>推送方式，让视图更少依赖上下文对象，是视图获取数据优先使用方式，缺点是需要手动构建数组，有些繁琐，在不同地方渲染时容易出错。</p>
<h3 id="视图间共享数据" tabindex="-1"><a class="header-anchor" href="#视图间共享数据"><span>视图间共享数据</span></a></h3>
<p><code v-pre>yii\base\View</code> 视图组件提供 [[yii\base\View::params]] 参数属性来让不同视图共享数据。例如在 <code v-pre>about</code> 视图中，可使用如下代码指定当前 breadcrumbs 的当前部分。</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token variable">$this</span><span class="token operator">-></span><span class="token property">params</span><span class="token punctuation">[</span><span class="token string single-quoted-string">'breadcrumbs'</span><span class="token punctuation">]</span><span class="token punctuation">[</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token string single-quoted-string">'About Us'</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p>在 <a href="https://github.com/yiisoft/yii2/blob/master/docs/guide-zh-CN/structure-views.md#layouts" target="_blank" rel="noopener noreferrer">布局</a> 文件（也是一个视图）中，可使用依次加入到 [[yii\base\View::params]] 数组的值来生成显示 breadcrumbs：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token php language-php"><span class="token delimiter important">&lt;?=</span> <span class="token class-name class-name-fully-qualified static-context">yii<span class="token punctuation">\</span>widgets<span class="token punctuation">\</span>Breadcrumbs</span><span class="token operator">::</span><span class="token function">widget</span><span class="token punctuation">(</span><span class="token punctuation">[</span></span>
<span class="line">    <span class="token string single-quoted-string">'links'</span> <span class="token operator">=></span> <span class="token keyword">isset</span><span class="token punctuation">(</span><span class="token variable">$this</span><span class="token operator">-></span><span class="token property">params</span><span class="token punctuation">[</span><span class="token string single-quoted-string">'breadcrumbs'</span><span class="token punctuation">]</span><span class="token punctuation">)</span> <span class="token operator">?</span> <span class="token variable">$this</span><span class="token operator">-></span><span class="token property">params</span><span class="token punctuation">[</span><span class="token string single-quoted-string">'breadcrumbs'</span><span class="token punctuation">]</span> <span class="token punctuation">:</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">,</span></span>
<span class="line"><span class="token punctuation">]</span><span class="token punctuation">)</span> <span class="token delimiter important">?></span></span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h2 id="布局" tabindex="-1"><a class="header-anchor" href="#布局"><span>布局</span></a></h2>
<p>布局是一种特殊的视图，代表多个视图的公共部分，例如，大多数Web应用共享相同的页头和页尾， 在每个视图中重复相同的页头和页尾，更好的方式是将这些公共放到一个布局中，渲染内容视图后在合适的地方嵌入到布局中。</p>
<h3 id="创建布局" tabindex="-1"><a class="header-anchor" href="#创建布局"><span>创建布局</span></a></h3>
<p>由于布局也是视图，它可像普通视图一样创建，布局默认存储在 <code v-pre>@app/views/layouts</code> 路径下，<a href="https://github.com/yiisoft/yii2/blob/master/docs/guide-zh-CN/structure-modules.md" target="_blank" rel="noopener noreferrer">模块</a> 中使用的布局应存储在 [[yii\base\Module::basePath]] 模块目录下的 <code v-pre>views/layouts</code> 路径下，可配置 [[yii\base\Module::layoutPath]] 来自定义应用或模块的布局默认路径。</p>
<p>如下示例为一个布局大致内容，注意作为示例，简化了很多代码，在实际中，你可能想添加更多内容，如头部标签，主菜单等。</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token php language-php"><span class="token delimiter important">&lt;?php</span></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">yii<span class="token punctuation">\</span>helpers<span class="token punctuation">\</span>Html</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token comment">/* @var $this yii\web\View */</span></span>
<span class="line"><span class="token comment">/* @var $content string 字符串 */</span></span>
<span class="line"><span class="token delimiter important">?></span></span></span>
<span class="line"><span class="token php language-php"><span class="token delimiter important">&lt;?php</span> <span class="token variable">$this</span><span class="token operator">-></span><span class="token function">beginPage</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token delimiter important">?></span></span></span>
<span class="line"><span class="token doctype"><span class="token punctuation">&lt;!</span><span class="token doctype-tag">DOCTYPE</span> <span class="token name">html</span><span class="token punctuation">></span></span></span>
<span class="line"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>html</span> <span class="token attr-name">lang</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>en<span class="token punctuation">"</span></span><span class="token punctuation">></span></span></span>
<span class="line"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>head</span><span class="token punctuation">></span></span></span>
<span class="line">    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>meta</span> <span class="token attr-name">charset</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>UTF-8<span class="token punctuation">"</span></span><span class="token punctuation">/></span></span></span>
<span class="line">    <span class="token php language-php"><span class="token delimiter important">&lt;?=</span> <span class="token class-name static-context">Html</span><span class="token operator">::</span><span class="token function">csrfMetaTags</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token delimiter important">?></span></span></span>
<span class="line">    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>title</span><span class="token punctuation">></span></span><span class="token php language-php"><span class="token delimiter important">&lt;?=</span> <span class="token class-name static-context">Html</span><span class="token operator">::</span><span class="token function">encode</span><span class="token punctuation">(</span><span class="token variable">$this</span><span class="token operator">-></span><span class="token property">title</span><span class="token punctuation">)</span> <span class="token delimiter important">?></span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>title</span><span class="token punctuation">></span></span></span>
<span class="line">    <span class="token php language-php"><span class="token delimiter important">&lt;?php</span> <span class="token variable">$this</span><span class="token operator">-></span><span class="token function">head</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token delimiter important">?></span></span></span>
<span class="line"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>head</span><span class="token punctuation">></span></span></span>
<span class="line"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>body</span><span class="token punctuation">></span></span></span>
<span class="line"><span class="token php language-php"><span class="token delimiter important">&lt;?php</span> <span class="token variable">$this</span><span class="token operator">-></span><span class="token function">beginBody</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token delimiter important">?></span></span></span>
<span class="line">    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>header</span><span class="token punctuation">></span></span>My Company<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>header</span><span class="token punctuation">></span></span></span>
<span class="line">    <span class="token php language-php"><span class="token delimiter important">&lt;?=</span> <span class="token variable">$content</span> <span class="token delimiter important">?></span></span></span>
<span class="line">    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>footer</span><span class="token punctuation">></span></span><span class="token entity named-entity" title="&copy;">&amp;copy;</span> 2014 by My Company<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>footer</span><span class="token punctuation">></span></span></span>
<span class="line"><span class="token php language-php"><span class="token delimiter important">&lt;?php</span> <span class="token variable">$this</span><span class="token operator">-></span><span class="token function">endBody</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token delimiter important">?></span></span></span>
<span class="line"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>body</span><span class="token punctuation">></span></span></span>
<span class="line"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>html</span><span class="token punctuation">></span></span></span>
<span class="line"><span class="token php language-php"><span class="token delimiter important">&lt;?php</span> <span class="token variable">$this</span><span class="token operator">-></span><span class="token function">endPage</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token delimiter important">?></span></span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>如上所示，布局生成每个页面通用的HTML标签，在 <code v-pre>&lt;body&gt;</code> 标签中，打印 <code v-pre>$content</code> 变量，<code v-pre>$content</code> 变量代表当 [[yii\base\Controller::render()]] 控制器渲染方法调用时传递到布局的内容视图渲染结果。</p>
<p>大多数视图应调用上述代码中的如下方法，这些方法触发关于渲染过程的事件，这样其他地方注册的脚本和标签会添加到这些方法调用的地方。</p>
<ul>
<li>[[yii\base\View::beginPage()]]: 该方法应在布局的开始处调用，它触发表明页面开始的 [[yii\base\View::EVENT_BEGIN_PAGE]] 事件。</li>
<li>[[yii\base\View::endPage()]]: 该方法应在布局的结尾处调用，它触发表明页面结尾的 [[yii\base\View::EVENT_END_PAGE]] 事件。</li>
<li>[[yii\web\View::head()]]: 该方法应在 HTML 页面的 <code v-pre>&lt;head&gt;</code> 标签中调用，它生成一个占位符，在页面渲染结束时会被注册的头部HTML代码（如，link标签, meta标签）替换。</li>
<li>[[yii\web\View::beginBody()]]: 该方法应在 <code v-pre>&lt;body&gt;</code> 标签的开始处调用，它触发 [[yii\web\View::EVENT_BEGIN_BODY]] 事件并生成一个占位符，会被注册的 HTML 代码（如JavaScript）在页面主体开始处替换。</li>
<li>[[yii\web\View::endBody()]]: 该方法应在 <code v-pre>&lt;body&gt;</code> 标签的结尾处调用，它触发 [[yii\web\View::EVENT_END_BODY]] 事件并生成一个占位符，会被注册的 HTML 代码（如JavaScript）在页面主体结尾处替换。</li>
</ul>
<h3 id="布局中访问数据" tabindex="-1"><a class="header-anchor" href="#布局中访问数据"><span>布局中访问数据</span></a></h3>
<p>在布局中可访问两个预定义变量：<code v-pre>$this</code> 和 <code v-pre>$content</code>，前者对应和普通视图类似的 <code v-pre>yii\base\View</code> 视图组件，后者包含调用 [[yii\base\Controller::render()]] 方法渲染内容视图的结果。</p>
<p>如果想在布局中访问其他数据，必须使用 <a href="https://github.com/yiisoft/yii2/blob/master/docs/guide-zh-CN/structure-views.md#accessing-data-in-views" target="_blank" rel="noopener noreferrer">视图中访问数据</a> 一节介绍的拉取方式，如果想从内容视图中传递数据到布局，可使用 <a href="https://github.com/yiisoft/yii2/blob/master/docs/guide-zh-CN/structure-views.md#sharing-data-among-views" target="_blank" rel="noopener noreferrer">视图间共享数据</a> 一节中的方法。</p>
<h3 id="使用布局" tabindex="-1"><a class="header-anchor" href="#使用布局"><span>使用布局</span></a></h3>
<p>如 <a href="https://github.com/yiisoft/yii2/blob/master/docs/guide-zh-CN/structure-views.md#rendering-in-controllers" target="_blank" rel="noopener noreferrer">控制器中渲染</a> 一节描述，当控制器调用 [[yii\base\Controller::render()]] 方法渲染视图时，会同时使用布局到渲染结果中，默认会使用 <code v-pre>@app/views/layouts/main.php</code> 布局文件。</p>
<p>可配置 [[yii\base\Application::layout]] 或 [[yii\base\Controller::layout]] 使用其他布局文件，前者管理所有控制器的布局，后者覆盖前者来控制单个控制器布局。例如，如下代码使 <code v-pre>post</code> 控制器渲染视图时使用 <code v-pre>@app/views/layouts/post.php</code> 作为布局文件，假如 <code v-pre>layout</code> 属性没改变，控制器默认使用 <code v-pre>@app/views/layouts/main.php</code> 作为布局文件。</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">namespace</span> <span class="token package">app<span class="token punctuation">\</span>controllers</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">yii<span class="token punctuation">\</span>web<span class="token punctuation">\</span>Controller</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">class</span> <span class="token class-name-definition class-name">PostController</span> <span class="token keyword">extends</span> <span class="token class-name">Controller</span></span>
<span class="line"><span class="token punctuation">{</span></span>
<span class="line">    <span class="token keyword">public</span> <span class="token variable">$layout</span> <span class="token operator">=</span> <span class="token string single-quoted-string">'post'</span><span class="token punctuation">;</span></span>
<span class="line">    <span class="token comment">// ...</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>对于模块中的控制器，可配置模块的 [[yii\base\Module::layout]] 属性指定布局文件应用到模块的所有控制器。</p>
<p>由于 <code v-pre>layout</code> 可在不同层级（控制器、模块，应用）配置，在幕后Yii使用两步来决定控制器实际使用的布局。</p>
<p>第一步，它决定布局的值和上下文模块：</p>
<ul>
<li>如果控制器的 [[yii\base\Controller::layout]] 属性不为空null，使用它作为布局的值， 控制器的 [[yii\base\Controller::module]] 模块作为上下文模块。</li>
<li>如果 [[yii\base\Controller::layout]] 为空，从控制器的祖先模块（包括应用）开始找 第一个[[yii\base\Module::layout]] 属性不为空的模块，使用该模块作为上下文模块，并将它的[[yii\base\Module::layout]] 的值作为布局的值，如果都没有找到，表示不使用布局。</li>
</ul>
<p>第二步，它决定第一步中布局的值和上下文模块对应到实际的布局文件，布局的值可为：</p>
<ul>
<li>路径别名 (如 <code v-pre>@app/views/layouts/main</code>).</li>
<li>绝对路径 (如 <code v-pre>/main</code>): 布局的值以斜杠开始，在应用的 [[yii\base\Application::layoutPath]] 布局路径中查找实际的布局文件，布局路径默认为 <code v-pre>@app/views/layouts</code>。</li>
<li>相对路径 (如 <code v-pre>main</code>): 在上下文模块的 [[yii\base\Module::layoutPath]] 布局路径中查找实际的布局文件，布局路径默认为 [[yii\base\Module::basePath]] 模块目录下的 <code v-pre>views/layouts</code> 目录。</li>
<li>布尔值 <code v-pre>false</code>: 不使用布局。</li>
</ul>
<p>布局的值没有包含文件扩展名，默认使用 <code v-pre>.php</code>作为扩展名。</p>
<h3 id="嵌套布局" tabindex="-1"><a class="header-anchor" href="#嵌套布局"><span>嵌套布局</span></a></h3>
<p>有时候你想嵌套一个布局到另一个，例如，在Web站点不同地方，想使用不同的布局，同时这些布局共享相同的生成全局 HTML5 页面结构的基本布局，可以在子布局中调用 [[yii\base\View::beginContent()]] 和 [[yii\base\View::endContent()]] 方法，如下所示：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token php language-php"><span class="token delimiter important">&lt;?php</span> <span class="token variable">$this</span><span class="token operator">-></span><span class="token function">beginContent</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'@app/views/layouts/base.php'</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token delimiter important">?></span></span></span>
<span class="line"></span>
<span class="line">...child layout content here...</span>
<span class="line"></span>
<span class="line"><span class="token php language-php"><span class="token delimiter important">&lt;?php</span> <span class="token variable">$this</span><span class="token operator">-></span><span class="token function">endContent</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token delimiter important">?></span></span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>如上所示，子布局内容应在 [[yii\base\View::beginContent()]] 和 [[yii\base\View::endContent()]] 方法之间，传给 [[yii\base\View::beginContent()]] 的参数指定父布局，父布局可为布局文件或别名。使用以上方式可多层嵌套布局。</p>
<h3 id="使用数据块" tabindex="-1"><a class="header-anchor" href="#使用数据块"><span>使用数据块</span></a></h3>
<p>数据块可以在一个地方指定视图内容在另一个地方显示，通常和布局一起使用，例如，可在内容视图中定义数据块在布局中显示它。</p>
<p>调用 [[yii\base\View::beginBlock()]] 和 [[yii\base\View::endBlock()]] 来定义数据块，使用 <code v-pre>$view-&gt;blocks[$blockID]</code> 访问该数据块，其中 <code v-pre>$blockID</code> 为定义数据块时指定的唯一标识ID。</p>
<p>如下实例显示如何在内容视图中使用数据块让布局使用。</p>
<p>首先，在内容视图中定一个或多个数据块：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line">...</span>
<span class="line"></span>
<span class="line"><span class="token php language-php"><span class="token delimiter important">&lt;?php</span> <span class="token variable">$this</span><span class="token operator">-></span><span class="token function">beginBlock</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'block1'</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token delimiter important">?></span></span></span>
<span class="line"></span>
<span class="line">...content of block1...</span>
<span class="line"></span>
<span class="line"><span class="token php language-php"><span class="token delimiter important">&lt;?php</span> <span class="token variable">$this</span><span class="token operator">-></span><span class="token function">endBlock</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token delimiter important">?></span></span></span>
<span class="line"></span>
<span class="line">...</span>
<span class="line"></span>
<span class="line"><span class="token php language-php"><span class="token delimiter important">&lt;?php</span> <span class="token variable">$this</span><span class="token operator">-></span><span class="token function">beginBlock</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'block3'</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token delimiter important">?></span></span></span>
<span class="line"></span>
<span class="line">...content of block3...</span>
<span class="line"></span>
<span class="line"><span class="token php language-php"><span class="token delimiter important">&lt;?php</span> <span class="token variable">$this</span><span class="token operator">-></span><span class="token function">endBlock</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token delimiter important">?></span></span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>然后，在布局视图中，数据块可用的话会渲染数据块，如果数据未定义则显示一些默认内容。</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line">...</span>
<span class="line"><span class="token php language-php"><span class="token delimiter important">&lt;?php</span> <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token keyword">isset</span><span class="token punctuation">(</span><span class="token variable">$this</span><span class="token operator">-></span><span class="token property">blocks</span><span class="token punctuation">[</span><span class="token string single-quoted-string">'block1'</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">:</span> <span class="token delimiter important">?></span></span></span>
<span class="line">    <span class="token php language-php"><span class="token delimiter important">&lt;?=</span> <span class="token variable">$this</span><span class="token operator">-></span><span class="token property">blocks</span><span class="token punctuation">[</span><span class="token string single-quoted-string">'block1'</span><span class="token punctuation">]</span> <span class="token delimiter important">?></span></span></span>
<span class="line"><span class="token php language-php"><span class="token delimiter important">&lt;?php</span> <span class="token keyword">else</span><span class="token punctuation">:</span> <span class="token delimiter important">?></span></span></span>
<span class="line">    ... default content for block1 ...</span>
<span class="line"><span class="token php language-php"><span class="token delimiter important">&lt;?php</span> <span class="token keyword">endif</span><span class="token punctuation">;</span> <span class="token delimiter important">?></span></span></span>
<span class="line"></span>
<span class="line">...</span>
<span class="line"></span>
<span class="line"><span class="token php language-php"><span class="token delimiter important">&lt;?php</span> <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token keyword">isset</span><span class="token punctuation">(</span><span class="token variable">$this</span><span class="token operator">-></span><span class="token property">blocks</span><span class="token punctuation">[</span><span class="token string single-quoted-string">'block2'</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">:</span> <span class="token delimiter important">?></span></span></span>
<span class="line">    <span class="token php language-php"><span class="token delimiter important">&lt;?=</span> <span class="token variable">$this</span><span class="token operator">-></span><span class="token property">blocks</span><span class="token punctuation">[</span><span class="token string single-quoted-string">'block2'</span><span class="token punctuation">]</span> <span class="token delimiter important">?></span></span></span>
<span class="line"><span class="token php language-php"><span class="token delimiter important">&lt;?php</span> <span class="token keyword">else</span><span class="token punctuation">:</span> <span class="token delimiter important">?></span></span></span>
<span class="line">    ... default content for block2 ...</span>
<span class="line"><span class="token php language-php"><span class="token delimiter important">&lt;?php</span> <span class="token keyword">endif</span><span class="token punctuation">;</span> <span class="token delimiter important">?></span></span></span>
<span class="line"></span>
<span class="line">...</span>
<span class="line"></span>
<span class="line"><span class="token php language-php"><span class="token delimiter important">&lt;?php</span> <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token keyword">isset</span><span class="token punctuation">(</span><span class="token variable">$this</span><span class="token operator">-></span><span class="token property">blocks</span><span class="token punctuation">[</span><span class="token string single-quoted-string">'block3'</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">:</span> <span class="token delimiter important">?></span></span></span>
<span class="line">    <span class="token php language-php"><span class="token delimiter important">&lt;?=</span> <span class="token variable">$this</span><span class="token operator">-></span><span class="token property">blocks</span><span class="token punctuation">[</span><span class="token string single-quoted-string">'block3'</span><span class="token punctuation">]</span> <span class="token delimiter important">?></span></span></span>
<span class="line"><span class="token php language-php"><span class="token delimiter important">&lt;?php</span> <span class="token keyword">else</span><span class="token punctuation">:</span> <span class="token delimiter important">?></span></span></span>
<span class="line">    ... default content for block3 ...</span>
<span class="line"><span class="token php language-php"><span class="token delimiter important">&lt;?php</span> <span class="token keyword">endif</span><span class="token punctuation">;</span> <span class="token delimiter important">?></span></span></span>
<span class="line">...</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h2 id="使用视图组件" tabindex="-1"><a class="header-anchor" href="#使用视图组件"><span>使用视图组件</span></a></h2>
<p><code v-pre>yii\base\View</code> 视图组件提供许多视图相关特性，可创建 <code v-pre>yii\base\View</code> 或它的子类实例来获取视图组件，大多数情况下主要使用 <code v-pre>view</code> 应用组件，可在 <a href="https://github.com/yiisoft/yii2/blob/master/docs/guide-zh-CN/structure-applications.md#application-configurations" target="_blank" rel="noopener noreferrer">应用配置</a> 中配置该组件，如下所示：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token punctuation">[</span></span>
<span class="line">    <span class="token comment">// ...</span></span>
<span class="line">    <span class="token string single-quoted-string">'components'</span> <span class="token operator">=></span> <span class="token punctuation">[</span></span>
<span class="line">        <span class="token string single-quoted-string">'view'</span> <span class="token operator">=></span> <span class="token punctuation">[</span></span>
<span class="line">            <span class="token string single-quoted-string">'class'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'app\components\View'</span><span class="token punctuation">,</span></span>
<span class="line">        <span class="token punctuation">]</span><span class="token punctuation">,</span></span>
<span class="line">        <span class="token comment">// ...</span></span>
<span class="line">    <span class="token punctuation">]</span><span class="token punctuation">,</span></span>
<span class="line"><span class="token punctuation">]</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>视图组件提供如下实用的视图相关特性，每项详情会在独立章节中介绍：</p>
<ul>
<li><a href="https://github.com/yiisoft/yii2/blob/master/docs/guide-zh-CN/output-theming.md" target="_blank" rel="noopener noreferrer">主题</a>: 允许为你的Web站点开发和修改主题；</li>
<li><a href="https://github.com/yiisoft/yii2/blob/master/docs/guide-zh-CN/caching-fragment.md" target="_blank" rel="noopener noreferrer">片段缓存</a>: 允许你在Web页面中缓存片段；</li>
<li><a href="https://github.com/yiisoft/yii2/blob/master/docs/guide-zh-CN/output-client-scripts.md" target="_blank" rel="noopener noreferrer">客户脚本处理</a>: 支持CSS 和 JavaScript 注册和渲染；</li>
<li><a href="https://github.com/yiisoft/yii2/blob/master/docs/guide-zh-CN/structure-assets.md" target="_blank" rel="noopener noreferrer">资源包处理</a>: 支持 <a href="https://github.com/yiisoft/yii2/blob/master/docs/guide-zh-CN/structure-assets.md" target="_blank" rel="noopener noreferrer">资源包</a>的注册和渲染；</li>
<li><a href="https://github.com/yiisoft/yii2/blob/master/docs/guide-zh-CN/tutorial-template-engines.md" target="_blank" rel="noopener noreferrer">模板引擎</a>: 允许你使用其他模板引擎，如 <a href="https://twig.symfony.com/" target="_blank" rel="noopener noreferrer">Twig</a>, <a href="https://www.smarty.net/" target="_blank" rel="noopener noreferrer">Smarty</a>。</li>
</ul>
<p>开发Web页面时，也可能频繁使用以下实用的小特性。</p>
<h3 id="设置页面标题" tabindex="-1"><a class="header-anchor" href="#设置页面标题"><span>设置页面标题</span></a></h3>
<p>每个 Web 页面应有一个标题，正常情况下标题的标签显示在 <a href="https://github.com/yiisoft/yii2/blob/master/docs/guide-zh-CN/structure-views.md#layouts" target="_blank" rel="noopener noreferrer">布局</a> 中， 但是实际上标题大多由内容视图而不是布局来决定，为解决这个问题， <code v-pre>yii\web\View</code> 提供 [[yii\web\View::title]] 标题属性可让标题信息从内容视图传递到布局中。</p>
<p>为利用这个特性，在每个内容视图中设置页面标题，如下所示：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token php language-php"><span class="token delimiter important">&lt;?php</span></span>
<span class="line"><span class="token variable">$this</span><span class="token operator">-></span><span class="token property">title</span> <span class="token operator">=</span> <span class="token string single-quoted-string">'My page title'</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token delimiter important">?></span></span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>然后在视图中，确保在 <code v-pre>&lt;head&gt;</code> 段中有如下代码：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>title</span><span class="token punctuation">></span></span><span class="token php language-php"><span class="token delimiter important">&lt;?=</span> <span class="token class-name static-context">Html</span><span class="token operator">::</span><span class="token function">encode</span><span class="token punctuation">(</span><span class="token variable">$this</span><span class="token operator">-></span><span class="token property">title</span><span class="token punctuation">)</span> <span class="token delimiter important">?></span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>title</span><span class="token punctuation">></span></span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><h3 id="注册meta元标签" tabindex="-1"><a class="header-anchor" href="#注册meta元标签"><span>注册Meta元标签</span></a></h3>
<p>Web页面通常需要生成各种元标签提供给不同的浏览器，如 <code v-pre>&lt;head&gt;</code> 中的页面标题，元标签通常在布局中生成。</p>
<p>如果想在内容视图中生成元标签，可在内容视图中调用 [[yii\web\View::registerMetaTag()]] 方法，如下所示：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token php language-php"><span class="token delimiter important">&lt;?php</span></span>
<span class="line"><span class="token variable">$this</span><span class="token operator">-></span><span class="token function">registerMetaTag</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token string single-quoted-string">'name'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'keywords'</span><span class="token punctuation">,</span> <span class="token string single-quoted-string">'content'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'yii, framework, php'</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token delimiter important">?></span></span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>以上代码会在视图组件中注册一个 “keywords” 元标签，在布局渲染后会渲染该注册的元标签，然后，如下 HTML 代码会插入到布局中调用 [[yii\web\View::head()]] 方法处：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token operator">&lt;</span>meta name<span class="token operator">=</span><span class="token string double-quoted-string">"keywords"</span> content<span class="token operator">=</span><span class="token string double-quoted-string">"yii, framework, php"</span><span class="token operator">></span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p>注意如果多次调用 [[yii\web\View::registerMetaTag()]] 方法，它会注册多个元标签，注册时不会检查是否重复。</p>
<p>为确保每种元标签只有一个，可在调用方法时指定键作为第二个参数，例如，如下代码注册两次 “description” 元标签，但是只会渲染第二个。</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token variable">$this</span><span class="token operator">-></span><span class="token function">registerMetaTag</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token string single-quoted-string">'name'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'description'</span><span class="token punctuation">,</span> <span class="token string single-quoted-string">'content'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'This is my cool website made with Yii!'</span><span class="token punctuation">]</span><span class="token punctuation">,</span> <span class="token string single-quoted-string">'description'</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token variable">$this</span><span class="token operator">-></span><span class="token function">registerMetaTag</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token string single-quoted-string">'name'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'description'</span><span class="token punctuation">,</span> <span class="token string single-quoted-string">'content'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'This website is about funny raccoons.'</span><span class="token punctuation">]</span><span class="token punctuation">,</span> <span class="token string single-quoted-string">'description'</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div></div></div><h3 id="注册链接标签" tabindex="-1"><a class="header-anchor" href="#注册链接标签"><span>注册链接标签</span></a></h3>
<p>和 <a href="https://github.com/yiisoft/yii2/blob/master/docs/guide-zh-CN/structure-views.md#adding-meta-tags" target="_blank" rel="noopener noreferrer">Meta标签</a> 类似，链接标签有时很实用，如自定义网站图标，指定Rss订阅，或授权OpenID到其他服务器。可以和元标签相似的方式调用 [[yii\web\View::registerLinkTag()]]，例如，在内容视图中注册链接标签如下所示：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token variable">$this</span><span class="token operator">-></span><span class="token function">registerLinkTag</span><span class="token punctuation">(</span><span class="token punctuation">[</span></span>
<span class="line">    <span class="token string single-quoted-string">'title'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'Live News for Yii'</span><span class="token punctuation">,</span></span>
<span class="line">    <span class="token string single-quoted-string">'rel'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'alternate'</span><span class="token punctuation">,</span></span>
<span class="line">    <span class="token string single-quoted-string">'type'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'application/rss+xml'</span><span class="token punctuation">,</span></span>
<span class="line">    <span class="token string single-quoted-string">'href'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'https://www.yiiframework.com/rss.xml/'</span><span class="token punctuation">,</span></span>
<span class="line"><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>上述代码会转换成</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token operator">&lt;</span>link title<span class="token operator">=</span><span class="token string double-quoted-string">"Live News for Yii"</span> rel<span class="token operator">=</span><span class="token string double-quoted-string">"alternate"</span> type<span class="token operator">=</span><span class="token string double-quoted-string">"application/rss+xml"</span> href<span class="token operator">=</span><span class="token string double-quoted-string">"https://www.yiiframework.com/rss.xml/"</span><span class="token operator">></span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p>和 [[yii\web\View::registerMetaTag()]] 类似，调用 [[yii\web\View::registerLinkTag()]] 指定键来避免生成重复链接标签。</p>
<h2 id="视图事件" tabindex="-1"><a class="header-anchor" href="#视图事件"><span>视图事件</span></a></h2>
<p>[[yii\base\View]] 视图组件会在视图渲染过程中触发几个事件，可以在内容发送给终端用户前，响应这些事件来添加内容到视图中或调整渲染结果。</p>
<ul>
<li>[[yii\base\View::EVENT_BEFORE_RENDER]]: 在控制器渲染文件开始时触发，该事件可设置 [[yii\base\ViewEvent::isValid]] 为 false 取消视图渲染。</li>
<li>[[yii\base\View::EVENT_AFTER_RENDER]]: 在布局中调用 [[yii\base\View::afterRender()]] 时触发， 该事件可获取[[yii\base\ViewEvent::output]]的渲染结果， 可修改该属性来修改渲染结果。</li>
<li>[[yii\base\View::EVENT_BEGIN_PAGE]]: 在布局调用 [[yii\base\View::beginPage()]] 时触发；</li>
<li>[[yii\base\View::EVENT_END_PAGE]]: 在布局调用 [[yii\base\View::endPage()]] 是触发；</li>
<li>[[yii\web\View::EVENT_BEGIN_BODY]]: 在布局调用 [[yii\web\View::beginBody()]] 时触发；</li>
<li>[[yii\web\View::EVENT_END_BODY]]: 在布局调用 [[yii\web\View::endBody()]] 时触发。</li>
</ul>
<p>例如，如下代码将当前日期添加到页面结尾处：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token class-name class-name-fully-qualified static-context"><span class="token punctuation">\</span>Yii</span><span class="token operator">::</span><span class="token variable">$app</span><span class="token operator">-></span><span class="token property">view</span><span class="token operator">-></span><span class="token function">on</span><span class="token punctuation">(</span><span class="token class-name static-context">View</span><span class="token operator">::</span><span class="token constant">EVENT_END_BODY</span><span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">    <span class="token keyword">echo</span> <span class="token function">date</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'Y-m-d'</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h2 id="渲染静态页面" tabindex="-1"><a class="header-anchor" href="#渲染静态页面"><span>渲染静态页面</span></a></h2>
<p>静态页面指的是大部分内容为静态的不需要控制器传递动态数据的Web页面。</p>
<p>可将HTML代码放置在视图中，在控制器中使用以下代码输出静态页面：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">actionAbout</span><span class="token punctuation">(</span><span class="token punctuation">)</span></span>
<span class="line"><span class="token punctuation">{</span></span>
<span class="line">    <span class="token keyword">return</span> <span class="token variable">$this</span><span class="token operator">-></span><span class="token function">render</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'about'</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>如果Web站点包含很多静态页面，多次重复相似的代码显得很繁琐，为解决这个问题，可以使用一个在控制器中称为 <code v-pre>yii\web\ViewAction</code> 的 <a href="https://github.com/yiisoft/yii2/blob/master/docs/guide-zh-CN/structure-controllers.md#standalone-actions" target="_blank" rel="noopener noreferrer">独立动作</a>。 例如：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">namespace</span> <span class="token package">app<span class="token punctuation">\</span>controllers</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">yii<span class="token punctuation">\</span>web<span class="token punctuation">\</span>Controller</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">class</span> <span class="token class-name-definition class-name">SiteController</span> <span class="token keyword">extends</span> <span class="token class-name">Controller</span></span>
<span class="line"><span class="token punctuation">{</span></span>
<span class="line">    <span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">actions</span><span class="token punctuation">(</span><span class="token punctuation">)</span></span>
<span class="line">    <span class="token punctuation">{</span></span>
<span class="line">        <span class="token keyword">return</span> <span class="token punctuation">[</span></span>
<span class="line">            <span class="token string single-quoted-string">'page'</span> <span class="token operator">=></span> <span class="token punctuation">[</span></span>
<span class="line">                <span class="token string single-quoted-string">'class'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'yii\web\ViewAction'</span><span class="token punctuation">,</span></span>
<span class="line">            <span class="token punctuation">]</span><span class="token punctuation">,</span></span>
<span class="line">        <span class="token punctuation">]</span><span class="token punctuation">;</span></span>
<span class="line">    <span class="token punctuation">}</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>现在如果你在 <code v-pre>@app/views/site/pages</code> 目录下创建名为 <code v-pre>about</code> 的视图，可通过如下 url 显示该视图：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line">http<span class="token punctuation">:</span><span class="token comment">//localhost/index.php?r=site/page&amp;view=about</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p><code v-pre>GET</code> 中 <code v-pre>view</code> 参数告知 <code v-pre>yii\web\ViewAction</code> 动作请求哪个视图，然后操作在 <code v-pre>@app/views/site/pages</code> 目录下寻找该视图，可配置 [[yii\web\ViewAction::viewPrefix]] 修改搜索视图的目录。</p>
<h2 id="最佳实践" tabindex="-1"><a class="header-anchor" href="#最佳实践"><span>最佳实践</span></a></h2>
<p>视图负责将模型的数据展示用户想要的格式，总之，视图</p>
<ul>
<li>应主要包含展示代码，如 HTML, 和简单的 PHP 代码来控制、格式化和渲染数据；</li>
<li>不应包含执行数据查询代码，这种代码放在模型中；</li>
<li>应避免直接访问请求数据，如 <code v-pre>$_GET</code>, <code v-pre>$_POST</code>，这种应在控制器中执行，如果需要请求数据，应由控制器推送到视图。</li>
<li>可读取模型属性，但不应修改它们。</li>
</ul>
<p>为使模型更易于维护，避免创建太复杂或包含太多冗余代码的视图，可遵循以下方法达到这个目标：</p>
<ul>
<li>使用 <a href="https://github.com/yiisoft/yii2/blob/master/docs/guide-zh-CN/structure-views.md#layouts" target="_blank" rel="noopener noreferrer">布局</a> 来展示公共代码（如，页面头部、尾部）；</li>
<li>将复杂的视图分成几个小视图，可使用上面描述的渲染方法将这些 小视图渲染并组装成大视图；</li>
<li>创建并使用 <a href="https://github.com/yiisoft/yii2/blob/master/docs/guide-zh-CN/structure-widgets.md" target="_blank" rel="noopener noreferrer">小部件</a> 作为视图的数据块；</li>
<li>创建并使用助手类在视图中转换和格式化数据。</li>
</ul>
<blockquote>
<p>💖喜欢本文档的，欢迎点赞、收藏、留言或转发，谢谢支持！<br>
作者邮箱：zhuzixian520@126.com，github地址：<a href="https://github.com/zhuzixian520" target="_blank" rel="noopener noreferrer">github.com/zhuzixian520</a></p>
</blockquote>
</div></template>


